﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DomainSearchTools.Common
{
    public class SysObserver<T> : IObservable<T>
    {
        #region Class
        private class Unsubscriber : IDisposable
        {
            private List<IObserver<T>> m_Observers { get; set; }
            private IObserver<T> m_Observer { get; set; }

            public Unsubscriber(List<IObserver<T>> observers, IObserver<T> observer)
            {
                this.m_Observers = observers;
                this.m_Observer = observer;
            }

            public void Dispose()
            {
                if (m_Observer != null && m_Observers.Contains(m_Observer))
                {
                    m_Observers.Remove(m_Observer);
                }
            }
        }
        #endregion

        #region Enum
        enum NotifyType
        {
            Next,
            Completed,
            Error
        }
        #endregion

        #region Var
        private List<IObserver<T>> _observers;
        #endregion

        #region Protected Property
        protected List<IObserver<T>> m_Observers
        {
            get
            {
                if (_observers == null)
                    _observers = new List<IObserver<T>>();
                return _observers;
            }
        }
        #endregion

        #region Private Method
        private void NotifyError(Exception error)
        {
            foreach (IObserver<T> observer in m_Observers)
            {
                observer.OnError(error);
            }
        }
        #endregion


        #region Protected Method
        protected void NotifyNext(T obj)
        {
            try
            {
                foreach (IObserver<T> observer in m_Observers)
                {
                    observer.OnNext(obj);
                }
            }
            catch (Exception e)
            {
                NotifyError(e);
            }
        }

        protected void NotifyCompleted()
        {
            try
            {
                foreach (IObserver<T> observer in m_Observers)
                {
                    observer.OnCompleted();
                }
            }
            catch (Exception e)
            {
                NotifyError(e);
            }
        }
        #endregion


        #region Public Method
        public IDisposable Subscribe(IObserver<T> observer)
        {
            if (!m_Observers.Contains(observer))
            {
                m_Observers.Add(observer);
            }
            return new Unsubscriber(m_Observers, observer);
        }
        #endregion
    }
}